package com.stylefeng.guns.core.util.appSecure.encoder;


import java.security.GeneralSecurityException;
import java.security.spec.KeySpec;
import java.util.UUID;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang.StringUtils;

import sun.misc.BASE64Decoder;  
import sun.misc.BASE64Encoder;  
 
public class UtilAES {

    private static final int IV_SIZE = 16;
    private static final int KEY_SIZE = 16;
    private static final int ITERATION_COUNT = 100;
    private static final String TRANSFORMATION = "AES/CBC/PKCS5PADDING";

    private static final byte[] IV = generateBytes("BroadDeep&Safe".getBytes(), IV_SIZE);
    private static final byte[] SALT = generateBytes("EverSec&BroadDeep$Mobile".getBytes(), KEY_SIZE);

    public static byte[] encrypt(byte[] data, String password) {
        return encryptData(data, IV, deriveKeySecurely(password, KEY_SIZE));
    }

    public static byte[] decrypt(byte[] data, String password) {
        return decryptData(data, IV, deriveKeySecurely(password, KEY_SIZE));
    }

    private static byte[] generateBytes(byte[] data, int size) {
        byte[] iv = new byte[size];
        int len = data.length;
        for (int i = 0; i < size; i++) {
            iv[i] = data[i % len];
        }
        return iv;
    }

    private static SecretKey deriveKeySecurely(String password, int keySizeInBytes) {
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), SALT, ITERATION_COUNT, keySizeInBytes * 8);
        try {
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
            return new SecretKeySpec(keyBytes, "AES");
        } catch (Exception e) {
            throw new RuntimeException("deriveKey", e);
        }

    }

    private static byte[] encryptOrDecrypt(byte[] data, SecretKey key, byte[] iv, boolean isEncrypt) {
        try {
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            return cipher.doFinal(data);
        } catch (GeneralSecurityException e) {
            throw new RuntimeException("encryptOrDecrypt", e);
        }
    }

    private static byte[] encryptData(byte[] data, byte[] iv, SecretKey key) {
        return encryptOrDecrypt(data, key, iv, true);
    }

    private static byte[] decryptData(byte[] data, byte[] iv, SecretKey key) {
        return encryptOrDecrypt(data, key, iv, false);
    }
    
    
    /**  
     * base 64 encode  
     * @param bytes 待编码的byte[]  
     * @return 编码后的base 64 code  
     */    
    public static String base64Encode(byte[] bytes){    
        return new BASE64Encoder().encode(bytes);    
    }    
        
    /**  
     * base 64 decode  
     * @param base64Code 待解码的base 64 code  
     * @return 解码后的byte[]  
     * @throws Exception  
     */    
    public static byte[] base64Decode(String base64Code) throws Exception{    
        return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);    
    }    
    
    //=======test===================
    public static void main(String[] args) {
    	testInner("".getBytes(), "d8623ac47ca33345e774de46f53ffeae");
    	
/*    	 UUID uuid = UUID.randomUUID();
         System.out.println(uuid);*/
    	
    	String signStrMD5 = HashUtil.md5(("90a37a82-d949-4c99-982f-832b7179db00"+"123456"+"1504504378482"+"d8623ac47ca33345e774de46f53ffeae").getBytes()); 
    	
    	System.out.println(signStrMD5.substring(signStrMD5.length()-16,signStrMD5.length()).toLowerCase());
    	
    	String str = UtilAES.base64Encode(UtilAES.encrypt("{'phonelist': [ { 'phone_num':'18511864420'}, { 'phone_num':'13096380795'}]  }".getBytes(),"d8623ac47ca33345e774de46f53ffeae"));
    	System.out.println(str);
    	
    	
    	String re = "Jk9vq9UoEsXAatfzEMfN8h8MjlVsiM1iZK382WutvbIATs/wUAoMtYMtyr+nQSUafqt4wWGw046BhWLrVjFFSqnPHvp6qhokN9wGSjhT2oY=";
    	String rd = "cr26gCPnHWmemJFdK1eYCYD+OVLdCZ4ISO36m3UBzLjpdWU7ydK4w82b6yl3PeMx0WwdhvpiSJFC\r\nQ5mbG+liVH2VxViq0J2g5yOwHyliTaJmLJSGAvUT0rs/kXLOa9IuT+uYTT2dkWUhDCYv1wvMsw==";
    	String r = null;
		try {
			r = new String(UtilAES.decrypt(UtilAES.base64Decode(rd),"d8623ac47ca33345e774de46f53ffeae"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} //解密
    	System.out.println(r);
	}
    
    private static void testInner(byte[] data, String password) {
        System.out.println("加密前:" + new String(data));

        byte[] encrypt = encrypt(data, password);
        System.out.println("加密后:" + new String(encrypt));

        byte[] decrypt = decrypt(encrypt, password);
        System.out.println("解密后:" + new String(decrypt));
    }
    

}

